﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Drawing;
using System.Globalization;
using System.Reflection;
using System.Text;
using System.Xml;
using System.Xml.Serialization;
using InkFx.WinControl.Core;
using InkFx.WinControl.Design;
using InkFx.WinControl.Utils;

namespace InkFx.WinControl.Theme
{
    /// <summary>
    /// 
    /// </summary>
    public class BaseTheme : ICloneable, IDisposable
    {
        private string m_Skin = string.Empty;
        private bool m_IsDisposed = false;
        private bool m_IsCloneing = false;

        /// <summary>
        /// 
        /// </summary>
        [XmlIgnore, Browsable(false), DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden), Localizable(false)]
        public virtual string Skin
        {
            get { return m_Skin; }
            set { m_Skin = (value ?? string.Empty).Trim(); }
        }
        /// <summary>
        /// 
        /// </summary>
        [XmlIgnore, Browsable(false), DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden), Localizable(false)]
        public virtual bool IsDisposed
        {
            get { return m_IsDisposed; }
        }
        /// <summary>
        /// 当前正在执行 皮肤克隆操作
        /// <para>如果是正在进行 克隆操作, 则不会在 设置某些属性值时 衍生赋值其他属性</para>
        /// </summary>
        [XmlIgnore, Browsable(false), DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden), Localizable(false)]
        public virtual bool IsCloneing
        {
            get { return m_IsCloneing; }
            protected set { m_IsCloneing = value; }
        }


        /// <summary>
        /// 
        /// </summary>
        /// <returns></returns>
        public virtual string GetThemeName()
        {
            Type type = this.GetType();
            string themeName = BaseTheme.GetThemeName(type);
            return themeName;
        }
        /// <summary>
        /// 
        /// </summary>
        /// <param name="type">Type: Type</param>
        /// <returns></returns>
        public static string GetThemeName(Type type)
        {
            ThemeAttribute attr = ReflectHelper.GetAttribute<ThemeAttribute>(type);
            if (attr != null && !Tools.IsNullOrWhiteSpace(attr.Name)) return attr.Name;

            string typeName = type.Name;
            if (typeName.StartsWith("Theme", StringComparison.InvariantCultureIgnoreCase)) return typeName.Substring(5);

            return typeName;
        }


        /// <summary>
        /// 
        /// </summary>
        /// <returns></returns>
        public virtual List<PropertyInfo> GetListXmlProp()
        {
            List<PropertyInfo> listProp = GetListXmlProp(this.GetType());
            return listProp;
        }
        /// <summary>
        /// 
        /// </summary>
        /// <param name="type">Type: Type</param>
        /// <returns></returns>
        public virtual List<PropertyInfo> GetListXmlProp(Type type)
        {
            if (type == null) return null;

            List<PropertyInfo> listTemp = new List<PropertyInfo>(type.GetProperties());
            //listTemp.RemoveAll(x => !x.CanWrite);

            List<PropertyInfo> listProp = new List<PropertyInfo>();
            foreach (PropertyInfo prop in listTemp)
            {
                bool hasXmlIgnore = ReflectHelper.HasAttribute<XmlIgnoreAttribute>(prop);
                if (hasXmlIgnore) continue;
                bool hasSoapIgnore = ReflectHelper.HasAttribute<SoapIgnoreAttribute>(prop);
                if (hasSoapIgnore) continue;
                listProp.Add(prop);
            }

            return listProp;
        }






        //public class NameAndXml
        //{
        //    public NameAndXml() { }
        //    public NameAndXml(string name, string xml)
        //    {
        //        this.Name = name;
        //        this.Xml = xml;
        //    }

        //    private string m_Name = string.Empty;
        //    private string m_Xml = string.Empty;

        //    public string Name
        //    {
        //        get { return m_Name; }
        //        set { m_Name = (value ?? string.Empty).Trim(); }
        //    }
        //    public string Xml
        //    {
        //        get { return m_Xml; }
        //        set { m_Xml = (value ?? string.Empty).Trim(); }
        //    }
        //}
        /// <summary>
        /// 
        /// </summary>
        public class XmlOrText
        {
            /// <summary>
            /// 构造函数
            /// </summary>
            public XmlOrText() { }
            /// <summary>
            /// 构造函数
            /// </summary>
            /// <param name="xml">Type: string</param>
            /// <param name="text">Type: string</param>
            public XmlOrText(string xml, string text)
            {
                this.Xml = xml;
                this.Text = text;
            }

            private string m_Text = string.Empty;
            private string m_Xml = string.Empty;

            /// <summary>
            /// 
            /// </summary>
            public string Xml
            {
                get { return m_Xml; }
                set { m_Xml = (value ?? string.Empty).Trim(); }
            }
            /// <summary>
            /// 
            /// </summary>
            public string Text
            {
                get { return m_Text; }
                set { m_Text = (value ?? string.Empty).Trim(); }
            }
        }



        /// <summary>
        /// 
        /// </summary>
        /// <returns></returns>
        public virtual object Clone()
        {
            var type = this.GetType();
            var clone = Activator.CreateInstance(type) as BaseTheme;
            if (clone == null) return null;

            try
            {
                clone.m_IsCloneing = true;

                PropertyInfo[] props = type.GetProperties();
                foreach (var prop in props)
                {
                    if (!prop.CanRead || !prop.CanWrite) continue;
                    object value = prop.GetValue(this, null);

                    if (value is ICloneable)
                    {
                        object value2 = ((ICloneable)value).Clone();
                        prop.SetValue(clone, value2, null);
                    }
                    else if (value.GetType().IsValueType)
                        prop.SetValue(clone, value, null);
                    else
                        throw new Exception(string.Format("无法对 '{0}' 的属性 '{1}' 执行克隆操作, 类型 '{0}' 必须 override 改写 Clone() 函数!", type, prop.Name));
                }
            }
            finally { clone.m_IsCloneing = false; }

            return clone;
        }
        /// <summary>
        /// 
        /// </summary>
        public virtual void Dispose()
        {
            m_IsDisposed = true;
        }


    }

}
